<template>
    <div>

        <div class="buttonSound">
            <!-- 按钮 -->
            <el-button class="buttonforsound" @click="recOpen">打开录音,请求权限😋</el-button>
            <el-button class="buttonforsound" @click="recStart">开始录音🔊</el-button>
            <el-button class="buttonforsound" @click="recStop">结束录音⏰</el-button>
            <el-button class="buttonforsound" @click="recPlay" :disabled="!recBlob?true:false">本地试听💩</el-button>
        </div>
        <div style="text-align: center;">
            <p class="tip">以下是音频提示</p>
            <el-icon>
                <ArrowDown />
            </el-icon>
        </div>

        <div style="padding-top: 5px" class="soundcheckBorder">
            <!-- 波形绘制区域 -->
            <div style="display: inline-block; vertical-align: bottom">
                <div style="height: 100px; width: 300px" ref="recwave"></div>
            </div>


        </div>
        <div id="beginSound">
            <el-button size="large" class="uploadAudio" :disabled="!recBlob?true:false">上传录音😎</el-button>
        </div>
    </div>

</template>
<script setup lang='ts'>
    import { ElMessage } from 'element-plus'

    import { ref } from 'vue'
    //必须引入的核心
    import Recorder from 'recorder-core';
    import axios from 'axios'

    //引入mp3格式支持文件；如果需要多个格式支持，把这些格式的编码引擎js文件放到后面统统引入进来即可
    import 'recorder-core/src/engine/mp3';
    import 'recorder-core/src/engine/mp3-engine';
    //录制wav格式的用这一句就行
    import 'recorder-core/src/engine/wav';

    //可选的插件支持项，这个是波形可视化插件
    import 'recorder-core/src/extensions/waveview';
    //ts import 提示：npm包内已自带了.d.ts声明文件（不过是any类型）

    import useVoiceStore from '@/store/modules/voice'

    import useUserStore from '@/store/modules/user'

    let userStore = useUserStore()
    let voiceStore = useVoiceStore()

    let rec: any;
    // let recBlob: any;
    const recBlob = ref('')
    let wave: any;
    const recwave = ref(null);
    // 打开录音
    function recOpen() {
        //创建录音对象
        rec = Recorder({
            type: 'wav', //录音格式，可以换成wav等其他格式
            sampleRate: 16000, //录音的采样率，越大细节越丰富越细腻
            bitRate: 16, //录音的比特率，越大音质越好
            onProcess: (
                buffers: any,
                powerLevel: any,
                bufferDuration: any,
                bufferSampleRate: any,
                newBufferIdx: any,
                asyncEnd: any,
            ) => {
                //录音实时回调，大约1秒调用12次本回调
                //可实时绘制波形，实时上传（发送）数据
                if (wave) {
                    wave.input(buffers[buffers.length - 1], powerLevel, bufferSampleRate);
                }
            },
        });
        if (!rec) {
            ElMessage({
                type: 'success',
                message: '当前浏览器不支持录音功能！'
            })
            return;
        }
        //打开录音，获得权限
        rec.open(
            () => {
                ElMessage({
                    type: 'success',
                    message: '录音已打开！'
                })
                if (recwave.value) {
                    //创建音频可视化图形绘制对象
                    wave = Recorder.WaveView({ elem: recwave.value });
                }
            },
            (msg: any, isUserNotAllow: any) => {
                //用户拒绝了录音权限，或者浏览器不支持录音
                // console.log((isUserNotAllow ? 'UserNotAllow，' : '') + '无法录音:' + msg);
                ElMessage({
                    type: 'error',
                    message: (isUserNotAllow ? 'UserNotAllow，' : '') + '无法录音:' + msg
                })
            },
        );
    }
    // 开始录音
    function recStart() {
        if (!rec) {
            ElMessage({
                type: 'error',
                message: '未打开录音'
            })

            return;
        }
        rec.start();
        ElMessage({
            type: 'success',
            message: '已开始录音'
        })
    }
    // 结束录音
    function recStop() {
        if (!rec) {
            ElMessage({
                type: 'success',
                message: '未打开录音'
            })
            return;
        }
        rec.stop(
            (blob: any, duration: any) => {


                //blob就是我们要的录音文件对象，可以上传，或者本地播放
                recBlob.value = blob;
                //简单利用URL生成本地文件地址，此地址只能本地使用，比如赋值给audio.src进行播放，赋值给a.href然后a.click()进行下载（a需提供download="xxx.mp3"属性）
                const localUrl = (window.URL || window.webkitURL).createObjectURL(blob);
                ElMessage({
                    type: 'success',
                    message: '录音成功'
                })
                console.log('录音成功', blob, localUrl, '时长:' + duration + 'ms');

                voiceStore.loadBlob(blob)
                // upload(blob); //把blob文件上传到服务器
                rec.close(); //关闭录音，释放录音资源，当然可以不释放，后面可以连续调用start
                rec = null;
            },
            (err: any) => {
                // console.error('结束录音出错：' + err);
                ElMessage({
                    type: 'error',
                    message: '结束录音出错：' + err
                })
                rec.close(); //关闭录音，释放录音资源，当然可以不释放，后面可以连续调用start
                rec = null;
            },
        );
    }
    // 上传录音
    const upload = (blob: any) => {
        return new Promise((resolve, reject) => {
            console.log('触发子组件事件');
            //使用FormData用multipart/form-data表单上传文件
            //或者将blob文件用FileReader转成base64纯文本编码，使用普通application/x-www-form-urlencoded表单上传
            const form = new FormData();
            // 生成随机文件名
            const randomFileName = Math.random().toString(36).substring(2) + '.wav';
            form.append('file', blob, randomFileName); // 和普通form表单并无二致，后端接收到upfile参数的文件，文件名为recorder.mp3
            // form.append('key', 'value'); // 其他参数

            // 在这里添加请求头
            const config = {
                headers: {
                    'Authorization': userStore.userToken,
                    'Content-Type': 'multipart/form-data'
                }
            };

            axios.post('api/media/uploadFile', form, config)
                .then(response => {
                    console.log('上传成功');
                    resolve(response.data); // 返回成功的结果
                })
                .catch(error => {
                    console.error('上传失败' + error.message);
                    reject(error); // 返回失败的结果
                });
        });
    };
    // 定义一个全局变量来保存上一次创建的 audio 元素
    let previousAudio = null;

    function recPlay() {
        // 检查上一次创建的 audio 元素是否存在，并进行删除
        if (previousAudio) {
            previousAudio.parentNode.removeChild(previousAudio);
            previousAudio = null;
        }

        // 本地播放录音试听，可以直接用 URL 把 blob 转换成本地播放地址，用 audio 进行播放
        const localUrl = URL.createObjectURL(recBlob.value);
        const audio = document.createElement('audio');
        audio.controls = true;

        const parentElement = document.getElementById('beginSound');
        parentElement.appendChild(audio);

        audio.src = localUrl;
        audio.play();

        // 设置当前创建的 audio 元素为全局变量
        previousAudio = audio;

        // 注意不用了时需要 revokeObjectURL，否则霸占内存
        setTimeout(function () {
            URL.revokeObjectURL(audio.src);
        }, 5000);
    }

    defineExpose({
        upload
    })
</script>
<style scoped>
    .soundcheckBorder {
        margin-top: 20px;
        border-radius: 1rem 1rem 1rem 1rem;
        text-align: center;
        border: 1px solid #cccccc;
    }

    .buttonSound {
        display: flex;
        align-items: center;
        justify-content: space-between;
        flex-wrap: wrap;
    }

    #beginSound {
        margin-top: 10px;
    }

    #beginSound {
        text-align: center;
        display: flex;
        justify-content: space-around;
        align-items: center;


    }
</style>